// $Id: library.cpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#define XPCOM_SOURCE

#include <xpcom/config.hpp>
#include <xpcom/assert.hpp>
#include <xpcom/exception.hpp>
#include <xpcom/library.hpp>
#include <xpcom/ptr.hpp>
#include <xpcom/proxy/bool.hpp>
#include <xpcom/proxy/ptr.hpp>
#include "api/xpcom.hpp"
#include "nsIComponentManager.hpp"
#include "nsIComponentRegistrar.hpp"
#include "nsIDebug.hpp"
#include "nsIFile.hpp"
#include "nsILocalFile.hpp"
#include "nsIMemory.hpp"
#include "nsIServiceManager.hpp"
#include "nsITraceRefcnt.hpp"

namespace xpcom {

library::library() :
    service_manager_(0)
{
    ::NS_InitXPCOM2(&service_manager_, 0, 0) | throw_exception;

    XPCOM_ASSERT(service_manager_);
}

library::library(
        noref_ptr<nsIFile> bin_dir,
        noref_ptr<nsIDirectoryServiceProvider> dir_provider)
{
    ::NS_InitXPCOM2(
            &service_manager_, bin_dir.get(), dir_provider.get())
            | throw_exception;

    XPCOM_ASSERT(service_manager_);
}

library::library(
        noref_ptr<nsIFile> bin_dir,
        noref_ptr<nsIDirectoryServiceProvider> dir_provider,
        const static_module_info* static_components,
        uint32_t component_count)
{
    ::NS_InitXPCOM3(
            &service_manager_, bin_dir.get(), dir_provider.get(),
            reinterpret_cast<const nsStaticModuleInfo*>(static_components),
            component_count)
            | throw_exception;

    XPCOM_ASSERT(service_manager_);
}

library::~library()
{
    if (service_manager_) {
        // XXX service_manager_ will be released during shutdown
        // And return codes are ignored
        ::NS_ShutdownXPCOM(service_manager_);
    }
}

ref_ptr<nsIServiceManager> library::service_manager()
{
    ref_ptr<nsIServiceManager> ret;
    ::NS_GetServiceManager(proxy::ptr_out(ret)) | throw_exception;
    return ret;
}

ref_ptr<nsIComponentManager> library::component_manager()
{
    ref_ptr<nsIComponentManager> ret;
    ::NS_GetComponentManager(proxy::ptr_out(ret)) | throw_exception;
    return ret;
}

ref_ptr<nsIComponentRegistrar> library::component_registrar()
{
    ref_ptr<nsIComponentRegistrar> ret;
    ::NS_GetComponentRegistrar(proxy::ptr_out(ret)) | throw_exception;
    return ret;
}

ref_ptr<nsIMemory> library::memory_manager()
{
    ref_ptr<nsIMemory> ret;
    ::NS_GetMemoryManager(proxy::ptr_out(ret)) | throw_exception;
    return ret;
}

ref_ptr<nsIDebug> library::debug_manager()
{
    ref_ptr<nsIDebug> ret;
    ::NS_GetDebug(proxy::ptr_out(ret)) | throw_exception;
    return ret;
}

ref_ptr<nsITraceRefcnt> library::trace_refcnt_manager()
{
    ref_ptr<nsITraceRefcnt> ret;
    ::NS_GetTraceRefcnt(proxy::ptr_out(ret)) | throw_exception;
    return ret;
}

ref_ptr<nsIFile> new_file(const wstring& path, bool follow_links)
{
    return new_local_file(path, follow_links);
}

ref_ptr<nsIFile> new_native_file(const string& path, bool follow_links)
{
    return new_native_local_file(path, follow_links);
}

ref_ptr<nsILocalFile> new_local_file(const wstring& path, bool follow_links)
{
    ref_ptr<nsILocalFile> ret;
    ::NS_NewLocalFile(
            path, proxy::bool_in(follow_links), proxy::ptr_out(ret))
            | throw_exception;
    return ret;
}

ref_ptr<nsILocalFile> new_native_local_file(
        const string& path, bool follow_links)
{
    ref_ptr<nsILocalFile> ret;
    ::NS_NewNativeLocalFile(
            path, proxy::bool_in(follow_links), proxy::ptr_out(ret))
            | throw_exception;
    return ret;
}

} // namespace xpcom
